home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / debugger / ddd-1.000 / ddd-1 / ddd-1.4b / ddd / DataDisp.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-12  |  63.7 KB  |  2,620 lines

  1. // $Id: DataDisp.C,v 1.18 1996/01/12 14:20:15 zeller Exp $
  2. // Data Display
  3.  
  4. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  5. // Written by Dorothea Luetkehaus (luetke@ips.cs.tu-bs.de).
  6. // 
  7. // This file is part of the DDD Library.
  8. // 
  9. // The DDD Library is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU Library General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // The DDD Library is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU Library General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU Library General Public
  20. // License along with the DDD Library -- see the file COPYING.LIB.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 675 Mass Ave, Cambridge, MA 02139, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers at `ddd@ips.cs.tu-bs.de'.
  28.  
  29. char DataDisp_rcsid[] =
  30.     "$Id: DataDisp.C,v 1.18 1996/01/12 14:20:15 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #pragma implementation "Map.h"
  35. #endif
  36.  
  37. #define LOG_DISPLAYS 0
  38. #define LOG_COMPARE  0
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Implementation von DataDisp.h
  42. //-----------------------------------------------------------------------------
  43.  
  44. #include "DataDisp.h"
  45.  
  46. // includes von Nora-Zeugs
  47. #include "GraphEdit.h"   // fuer XtNgraph
  48. #include "StringBox.h"   // fuer StringBox::fontTable
  49. #include "ScrolledGE.h"
  50. #include "PannedGE.h"
  51. #include "VSEFlags.h"
  52. #include "VSLLib.h"
  53. #include "assert.h"
  54. #include "bool.h"
  55. #include "converters.h"
  56. #include "MString.h"
  57. #include "DestroyCB.h"
  58. #include "CompositeB.h"
  59. #include "TagBox.h"
  60. #include "cook.h"
  61.  
  62. // includes von Motif-Zeugs
  63. #include <Xm/MessageB.h>
  64. #include <Xm/RowColumn.h>  // fuer XmMenuPosition()
  65. #include <Xm/SelectioB.h>  // fuer XmCreatePromptDialog()
  66. #include <Xm/TextF.h>      // fuer XmTextFieldGetString()
  67. #include <Xm/Label.h>
  68. #include <Xm/List.h>
  69.  
  70. // includes eigener Sachen
  71. #include "DispNode.h" // fuer Konstruktoren
  72. #include "disp-read.h"
  73. #include "string-fun.h"
  74. #include "comm-manag.h"
  75. #include "Map.h"
  76. #include "mydialogs.h"
  77. #include "ddd.h"
  78. #include "ArgField.h"
  79. #include "verify.h"
  80.  
  81. // sonstige includes
  82. #include <iostream.h>
  83. #include <fstream.h> // fuer ofstream
  84. #include <iomanip.h>
  85. #include <ctype.h>
  86.  
  87. //-----------------------------------------------------------------------
  88. // Xt-Zeugs
  89. //-----------------------------------------------------------------------
  90. XtActionsRec DataDisp::actions [] = {
  91.     {"graph-select",         DataDisp::graph_selectAct},
  92.     {"graph-select-or-move", DataDisp::graph_select_or_moveAct},
  93.     {"graph-popup-menu",     DataDisp::graph_popupAct},
  94.     {"graph-dereference",    DataDisp::graph_dereferenceAct},
  95.     {"graph-detail",         DataDisp::graph_detailAct},
  96.     {"graph-rotate",         DataDisp::graph_rotateAct},
  97.     {"graph-dependent",      DataDisp::graph_dependentAct}
  98. };
  99.  
  100.  
  101.  
  102. // Popup-Menues - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  103. struct GraphItms { enum Itms {SelectAll, Refresh, NewArg, New}; };
  104. MMDesc DataDisp::graph_popup[] =
  105. {
  106.     {"selectAll", MMPush,               {DataDisp::selectAllCB}},
  107.     {"refresh",   MMPush,               {DataDisp::refreshCB}},
  108.     {"new_arg",   MMPush | MMUnmanaged, {DataDisp::popup_new_argCB}},
  109.     {"new",       MMPush,               {DataDisp::popup_newCB}},
  110.     MMEnd
  111. };
  112.  
  113. struct ValueItms { enum Itms {Dereference, Detail, Rotate, Dependent,
  114.                   Dummy, Disable, Delete }; };
  115.  
  116. MMDesc DataDisp::node_popup[] =
  117. {
  118.     {"dereference",   MMPush,   {DataDisp::dereferenceCB}},
  119.     {"detail",        MMPush,   {DataDisp::toggleDetailCB}},
  120.     {"rotate",        MMPush,   {DataDisp::toggleRotateCB}},
  121.     {"dependent",     MMPush,   {DataDisp::dependentCB}},
  122.     MMSep,
  123.     {"disable",       MMPush,   {DataDisp::toggleDisableCB}},
  124.     {"delete",        MMPush,   {DataDisp::deleteCB}},
  125.     MMEnd
  126. };
  127.  
  128. MMDesc DataDisp::graph_cmd_area[] =
  129. {
  130.     {"dereference",   MMPush, {DataDisp::dereferenceCB}},
  131.     {"detail",        MMPush, {DataDisp::toggleDetailCB}},
  132.     {"rotate",        MMPush, {DataDisp::toggleRotateCB}},
  133.     {"dependent",     MMPush, {DataDisp::dependentCB}},
  134.     MMSep,
  135.     {"disable",       MMPush, {DataDisp::toggleDisableCB}},
  136.     {"delete",        MMPush, {DataDisp::deleteCB}},
  137.     MMEnd
  138. };
  139.  
  140. struct DisplayItms { enum Itms {New, Dependent, Dereference, 
  141.                 ShowDetail, HideDetail,
  142.                 Enable, Disable, Delete}; };
  143.  
  144. MMDesc DataDisp::display_area[] =
  145. {
  146.     {"new",          MMPush,   {DataDisp::newCB }},
  147.     {"dependent",    MMPush,   {DataDisp::dependentCB }},
  148.     {"dereference",  MMPush,   {DataDisp::dereferenceCB }},
  149.     {"show_detail",  MMPush,   {DataDisp::showDetailCB}},
  150.     {"hide_detail",  MMPush,   {DataDisp::hideDetailCB}},
  151.     {"enable",       MMPush,   {DataDisp::enableCB }},
  152.     {"disable",      MMPush,   {DataDisp::disableCB }},
  153.     {"delete",       MMPush,   {DataDisp::deleteCB }},
  154.     MMEnd
  155. };
  156.  
  157. DispGraph *DataDisp::disp_graph             = 0;
  158. Delay     *DataDisp::delay                  = 0;
  159. Widget     DataDisp::graph_edit             = 0;
  160. Widget     DataDisp::last_origin            = 0;
  161. ArgField  *DataDisp::graph_arg              = 0;
  162. Widget     DataDisp::graph_cmd_w            = 0;
  163. Widget     DataDisp::edit_displays_dialog_w = 0;
  164. Widget     DataDisp::display_list_w         = 0;
  165. Widget     DataDisp::graph_popup_w          = 0;
  166. Widget     DataDisp::node_popup_w           = 0;
  167.  
  168. bool DataDisp::ignore_update_graph_editor_selection   = false;
  169. bool DataDisp::ignore_update_display_editor_selection = false;
  170.  
  171.  
  172. //----------------------------------------------------------------------------
  173. // Sensitivity
  174. //-----------------------------------------------------------------------------
  175.  
  176. inline void set_sensitive(Widget w, bool state)
  177. {
  178.     if (w == 0 || XtIsSensitive(w) == state)
  179.     return;
  180.     XtSetSensitive(w, state);
  181. }
  182.  
  183. static void set_label(Widget w, string label)
  184. {
  185.     MString new_label(label);
  186.     XmString old_label;
  187.     XtVaGetValues(w, XmNlabelString, &old_label, NULL);
  188.     if (!XmStringCompare(new_label.xmstring(), old_label))
  189.     {
  190.     XtVaSetValues(w,
  191.               XmNlabelString, new_label.xmstring(),
  192.               NULL);
  193.     }
  194.     XmStringFree(old_label);
  195. }
  196.  
  197. //-----------------------------------------------------------------------------
  198. // Button Callbacks
  199. //-----------------------------------------------------------------------------
  200. void DataDisp::dereferenceCB(Widget w, XtPointer, XtPointer)
  201. {
  202.     last_origin = w;
  203.  
  204.     DispNode *disp_node_arg   = selected_node();
  205.     DispValue *disp_value_arg = selected_value();
  206.     if (disp_node_arg == 0 || disp_value_arg == 0)
  207.     return;
  208.  
  209.     string display_expression = disp_value_arg->dereferenced_name();
  210.     disp_value_arg->dereference();
  211.     disp_node_arg->refresh();
  212.  
  213.     string nr = disp_node_arg->disp_nr();
  214.     dependent_displaySQ (display_expression, get_positive_nr(nr));
  215. }
  216.  
  217. void DataDisp::toggleDetailCB(Widget dialog, XtPointer, XtPointer)
  218. {
  219.     last_origin = dialog;
  220.  
  221.     bool changed = false;
  222.     MapRef ref;
  223.     for (DispNode* dn = disp_graph->first(ref); 
  224.      dn != 0;
  225.      dn = disp_graph->next(ref))
  226.     {
  227.     if (dn->selected())
  228.     {
  229.         DispValue *dv = dn->selected_value();
  230.         if (dv == 0)
  231.         dv = dn->value();
  232.         if (dv == 0)
  233.         continue;
  234.  
  235.         if (dv->collapsed())
  236.         dv->expand();
  237.         else
  238.         dv->collapse();
  239.         dn->refresh();
  240.         changed = true;
  241.     }
  242.     }
  243.  
  244.     if (changed)
  245.     refresh_graph_edit();
  246. }
  247.  
  248. void DataDisp::showDetailCB (Widget dialog, XtPointer, XtPointer)
  249. {
  250.     last_origin = dialog;
  251.  
  252.     bool changed = false;
  253.     MapRef ref;
  254.     for (DispNode* dn = disp_graph->first(ref); 
  255.      dn != 0;
  256.      dn = disp_graph->next(ref))
  257.     {
  258.     if (dn->selected())
  259.     {
  260.         DispValue *dv = dn->selected_value();
  261.         if (dv == 0)
  262.         dv = dn->value();
  263.         if (dv == 0)
  264.         continue;
  265.         
  266.         if (dv->collapsed())
  267.         {
  268.         dv->expand();
  269.         dn->refresh();
  270.         changed = true;
  271.         }
  272.     }
  273.     }
  274.  
  275.     if (changed)
  276.     refresh_graph_edit();
  277. }
  278.  
  279. void DataDisp::hideDetailCB (Widget dialog, XtPointer, XtPointer)
  280. {
  281.     last_origin = dialog;
  282.  
  283.     bool changed = false;
  284.     MapRef ref;
  285.     for (DispNode* dn = disp_graph->first(ref); 
  286.      dn != 0;
  287.      dn = disp_graph->next(ref))
  288.     {
  289.     if (dn->selected())
  290.     {
  291.         DispValue *dv = dn->selected_value();
  292.         if (dv == 0)
  293.         dv = dn->value();
  294.         if (dv == 0)
  295.         continue;
  296.  
  297.         if (dv->expanded())
  298.         {
  299.         dv->collapse();
  300.         dn->refresh();
  301.         changed = true;
  302.         }
  303.     }
  304.     }
  305.  
  306.     if (changed)
  307.     refresh_graph_edit();
  308. }
  309.  
  310. void DataDisp::toggleRotateCB(Widget w, XtPointer, XtPointer)
  311. {
  312.     last_origin = w;
  313.  
  314.     DispNode *disp_node_arg   = selected_node();
  315.     DispValue *disp_value_arg = selected_value();
  316.     if (disp_node_arg == 0 || disp_value_arg == 0)
  317.     return;
  318.  
  319.     if (disp_value_arg->horizontal_aligned())
  320.     disp_value_arg->align_vertical();
  321.     else
  322.     disp_value_arg->align_horizontal();
  323.  
  324.     disp_node_arg->refresh();
  325.     refresh_graph_edit();
  326. }
  327.  
  328.  
  329. void DataDisp::toggleDisableCB (Widget dialog, XtPointer, XtPointer)
  330. {
  331.     last_origin = dialog;
  332.  
  333.     int *disp_nrs = new int[disp_graph->count_all()];
  334.  
  335.     bool do_enable  = true;
  336.     bool do_disable = true;
  337.  
  338.     int i = 0;
  339.     MapRef ref;
  340.     for (DispNode* dn = disp_graph->first(ref); 
  341.      dn != 0;
  342.      dn = disp_graph->next(ref))
  343.     {
  344.     if (dn->selected())
  345.     {
  346.         string nr = dn->disp_nr();
  347.         disp_nrs[i++] = get_positive_nr(nr);
  348.         if (dn->enabled())
  349.         do_enable = false;
  350.         if (dn->disabled())
  351.         do_disable = false;
  352.     }
  353.     }
  354.  
  355.     if (i > 0)
  356.     {
  357.     if (do_enable)
  358.         enable_displaySQ (disp_nrs, i);
  359.     else if (do_disable)
  360.         disable_displaySQ (disp_nrs, i);
  361.     }
  362.  
  363.     delete[] disp_nrs;
  364. }
  365.  
  366. static void select_with_all_descendants(GraphNode *node)
  367. {
  368.     if (!node->selected())
  369.     {
  370.     node->selected() = true;
  371.     
  372.     for (GraphEdge *edge = node->firstFrom();
  373.          edge != 0; edge = node->nextFrom(edge))
  374.         select_with_all_descendants(edge->to());
  375.     }
  376. }
  377.  
  378. static void select_with_all_ancestors(GraphNode *node)
  379. {
  380.     if (!node->selected())
  381.     {
  382.     node->selected() = true;
  383.     
  384.     for (GraphEdge *edge = node->firstTo();
  385.          edge != 0; edge = node->nextTo(edge))
  386.         select_with_all_ancestors(edge->from());
  387.     }
  388. }
  389.  
  390. // Upon deletion, select the ancestor and all siblings
  391. void DataDisp::deleteCB (Widget dialog, XtPointer, XtPointer)
  392. {
  393.     last_origin = dialog;
  394.  
  395.     int count = disp_graph->count_all();
  396.     int *disp_nrs = new int[count];
  397.     GraphNode **ancestors   = new GraphNode *[count];
  398.     GraphNode **descendants = new GraphNode *[count];
  399.  
  400.     int i = 0;
  401.     int a = 0;
  402.     int d = 0;
  403.  
  404.     MapRef ref;
  405.     for (DispNode* dn = disp_graph->first(ref); 
  406.      dn != 0;
  407.      dn = disp_graph->next(ref))
  408.     {
  409.     if (dn->selected())
  410.     {
  411.         string nr = dn->disp_nr();
  412.         disp_nrs[i++] = get_positive_nr(nr);
  413.  
  414.         // Select all ancestors
  415.         GraphEdge *edge;
  416.         for (edge = dn->nodeptr()->firstTo();
  417.          edge != 0; edge = dn->nodeptr()->nextTo(edge))
  418.         {
  419.         GraphNode *ancestor = edge->from();
  420.         while (ancestor->isHint())
  421.             ancestor = ancestor->firstTo()->from();
  422.  
  423.         ancestors[a++] = ancestor;
  424.         }
  425.  
  426.         // Select all descendants
  427.         for (edge = dn->nodeptr()->firstFrom();
  428.          edge != 0; edge = dn->nodeptr()->nextFrom(edge))
  429.         {
  430.         GraphNode *descendant = edge->to();
  431.         while (descendant->isHint())
  432.             descendant = descendant->firstFrom()->to();
  433.  
  434.         descendants[d++] = descendant;
  435.         }
  436.     }
  437.     }
  438.  
  439.     if (i > 0)
  440.     delete_displaySQ (disp_nrs, i);
  441.  
  442.     while (a > 0)
  443.     select_with_all_descendants(ancestors[--a]);
  444.     while (d > 0)
  445.     select_with_all_ancestors(descendants[--d]);
  446.  
  447.     refresh_graph_edit();
  448.  
  449.     delete[] disp_nrs;
  450.     delete[] descendants;
  451.     delete[] ancestors;
  452. }
  453.  
  454.  
  455. void DataDisp::dependentCB(Widget w, XtPointer, XtPointer)
  456. {
  457.     last_origin = w;
  458.  
  459.     DispNode *disp_node_arg   = selected_node();
  460.     DispValue *disp_value_arg = selected_value();
  461.     if (disp_node_arg == 0 || disp_value_arg == 0)
  462.     return;
  463.  
  464.     string nr = disp_node_arg->disp_nr();
  465.     static int* disp_nr_ptr = new int;
  466.     *disp_nr_ptr = get_positive_nr(nr);
  467.  
  468.     static Widget dependent_display_dialog = 0;
  469.     if (!dependent_display_dialog) {
  470.  
  471.     dependent_display_dialog = 
  472.         verify(XmCreatePromptDialog (graph_edit,
  473.                      "dependent_display_dialog",
  474.                      NULL, 0));
  475.     Delay::register_shell(dependent_display_dialog);
  476.  
  477.     XtAddCallback (dependent_display_dialog, 
  478.                XmNhelpCallback, 
  479.                ImmediateHelpCB, 
  480.                NULL);
  481.     XtAddCallback (dependent_display_dialog, 
  482.                XmNokCallback, 
  483.                dependent_displayDCB, 
  484.                disp_nr_ptr);
  485.     }
  486.  
  487.     MString label(disp_value_arg->full_name());
  488.  
  489.     XtVaSetValues (dependent_display_dialog,
  490.            XmNtextString, label.xmstring(),
  491.            NULL);
  492.     XtManageChild (dependent_display_dialog);
  493. }
  494.  
  495.  
  496. void DataDisp::refreshCB(Widget w, XtPointer, XtPointer)
  497. {
  498.     last_origin = w;
  499.     refresh_displaySQ();
  500. }
  501.  
  502. void DataDisp::selectAllCB(Widget w, XtPointer, XtPointer)
  503. {
  504.     last_origin = w;
  505.     XtCallActionProc(graph_edit, 
  506.              "select-all", (XEvent *)0, (String *)0, 0);
  507.     refresh_graph_edit();
  508. }
  509.  
  510. void DataDisp::newCB(Widget w, XtPointer, XtPointer)
  511. {
  512.     last_origin = w;
  513.     new_displayCD();
  514. }
  515.  
  516. void DataDisp::enableCB(Widget w, XtPointer, XtPointer)
  517. {
  518.     last_origin = w;
  519.  
  520.     int *disp_nrs = new int[disp_graph->count_all()];
  521.  
  522.     int i = 0;
  523.     MapRef ref;
  524.     for (DispNode* dn = disp_graph->first(ref); 
  525.      dn != 0;
  526.      dn = disp_graph->next(ref))
  527.     {
  528.     if (dn->selected() && dn->disabled())
  529.     {
  530.         string nr = dn->disp_nr();
  531.         disp_nrs[i++] = get_positive_nr(nr);
  532.     }
  533.     }
  534.  
  535.     if (i > 0)
  536.     enable_displaySQ (disp_nrs, i);
  537.  
  538.     delete[] disp_nrs;
  539. }
  540.  
  541. void DataDisp::disableCB(Widget w, XtPointer, XtPointer)
  542. {
  543.     last_origin = w;
  544.  
  545.     int *disp_nrs = new int[disp_graph->count_all()];
  546.  
  547.     int i = 0;
  548.     MapRef ref;
  549.     for (DispNode* dn = disp_graph->first(ref); 
  550.      dn != 0;
  551.      dn = disp_graph->next(ref))
  552.     {
  553.     if (dn->selected() && dn->enabled())
  554.     {
  555.         string nr = dn->disp_nr();
  556.         disp_nrs[i++] = get_positive_nr(nr);
  557.     }
  558.     }
  559.  
  560.     if (i > 0)
  561.     disable_displaySQ (disp_nrs, i);
  562.  
  563.     delete[] disp_nrs;
  564. }
  565.  
  566. //-----------------------------------------------------------------------------
  567. // Popup-Callbacks
  568. //-----------------------------------------------------------------------------
  569. // ***************************************************************************
  570. //
  571. void DataDisp::popup_new_argCB (Widget    display_dialog,
  572.                 XtPointer client_data,
  573.                 XtPointer)
  574. {
  575.     last_origin = display_dialog;
  576.  
  577.     BoxPoint* p = (BoxPoint *) client_data;
  578.     new_displaySQ (source_arg->get_string(), p);
  579. }
  580.  
  581.  
  582. // ***************************************************************************
  583. //
  584. void DataDisp::popup_newCB (Widget    display_dialog,
  585.                 XtPointer client_data,
  586.                 XtPointer)
  587. {
  588.     last_origin = display_dialog;
  589.  
  590.     BoxPoint* p = (BoxPoint *) client_data;
  591.     new_displayCD (*p);
  592. }
  593.  
  594.  
  595. // ***************************************************************************
  596. //
  597. void DataDisp::dependent_displayDCB (Widget    dialog, 
  598.                      XtPointer client_data, 
  599.                      XtPointer call_data)
  600. {
  601.     last_origin = dialog;
  602.  
  603.     int* disp_nr_ptr = (int *) client_data;
  604.     XmSelectionBoxCallbackStruct *cbs = 
  605.     (XmSelectionBoxCallbackStruct *)call_data;
  606.     char *input;
  607.     switch (cbs->reason) {
  608.     case XmCR_OK :
  609.     XmStringGetLtoR(cbs->value, MSTRING_DEFAULT_CHARSET, &input);
  610.     if (input != "") {
  611.         dependent_displaySQ (input, *disp_nr_ptr);
  612.     }
  613.     break;
  614.     default:
  615.     // Falscher Fehler
  616.     assert (0);
  617.     break;
  618.     }
  619. }
  620.  
  621.  
  622. // ***************************************************************************
  623. // Wertet Dialog Callback aus und ruft new_displaySQ() entsprechend auf.
  624. // 
  625. void DataDisp::new_displayDCB (Widget    display_dialog,
  626.                    XtPointer client_data,
  627.                    XtPointer call_data)
  628. {
  629.     last_origin = display_dialog;
  630.  
  631.     BoxPoint* p = (BoxPoint *) client_data;
  632.     XmSelectionBoxCallbackStruct *cbs = 
  633.     (XmSelectionBoxCallbackStruct *)call_data;
  634.     char *input;
  635.  
  636.     switch (cbs->reason) {
  637.     case XmCR_OK :
  638.     XmStringGetLtoR(cbs->value, MSTRING_DEFAULT_CHARSET, &input);
  639.     if (string(input) != "")
  640.         new_displaySQ (input, p);
  641.     break;
  642.     default:
  643.     // Falscher Fehler
  644.     assert (0);
  645.     break;
  646.     }
  647. }
  648.  
  649.  
  650. //-----------------------------------------------------------------------------
  651. // Dialog-Erzeugung
  652. //-----------------------------------------------------------------------------
  653.  
  654. // ***************************************************************************
  655. // Erzeugt Dialog zur Eingabe einer neuen Display-Expression.
  656. // Wird ein Boxpoint uebergeben, so wird der neue Knoten dorthin gesetzt.
  657. // 
  658. void DataDisp::new_displayCD (BoxPoint box_point)
  659. {
  660.     static BoxPoint* p;
  661.     static Widget new_display_dialog = 0;
  662.     if (!new_display_dialog) {
  663.     p = new BoxPoint(box_point);
  664.     new_display_dialog = 
  665.         verify(XmCreatePromptDialog (graph_edit,
  666.                      "new_display_dialog",
  667.                      NULL, 0));
  668.     Delay::register_shell(new_display_dialog);
  669.     XtAddCallback (new_display_dialog, 
  670.                XmNhelpCallback, 
  671.                ImmediateHelpCB, 
  672.                NULL);
  673.     XtAddCallback (new_display_dialog,
  674.                XmNokCallback,
  675.                new_displayDCB,
  676.                p);
  677.     }
  678.     else {
  679.     *p = box_point;
  680.     }
  681.     XtManageChild (new_display_dialog);
  682. }
  683.  
  684.  
  685.  
  686. //-----------------------------------------------------------------------------
  687. // sonstige Procs
  688. //-----------------------------------------------------------------------------
  689.  
  690. // ***************************************************************************
  691. //
  692. void DataDisp::set_delay () 
  693. {
  694.     if (!delay)
  695.     delay = new Delay;
  696. }
  697. void DataDisp::unset_delay () 
  698. {
  699.     if (delay)
  700.     delete delay;
  701.     delay = 0;
  702. }
  703.  
  704. void DataDisp::set_handlers()
  705. {
  706.     source_arg->addHandler(Empty, source_argHP);
  707.     graph_arg->addHandler(Empty, graph_argHP);
  708.     graph_arg->addHandler(LosePrimary, graph_unselectHP);
  709.     gdb->addBusyHandler(ReadyForQuestion, gdb_ready_for_questionHP);
  710. }
  711.  
  712.  
  713.  
  714.  
  715. // ***************************************************************************
  716. // Graph neu zeichnen, und Sensitivitaeten neu setzen
  717. //
  718. void DataDisp::refresh_graph_edit ()
  719. {
  720.     static Graph* dummy = 0;
  721.     if (!dummy)
  722.     dummy = new Graph();
  723.     XtVaSetValues(graph_edit,
  724.           XtNgraph, dummy,
  725.           NULL);
  726.     XtVaSetValues(graph_edit,
  727.           XtNgraph, (Graph *)disp_graph,
  728.           NULL);
  729.     refresh_args();
  730.     fill_labels();
  731. }
  732.  
  733. // ***************************************************************************
  734. //
  735. inline int DataDisp::getDispNrAtPoint (BoxPoint point)
  736. {
  737.     GraphNode* gn = graphEditGetNodeAtPoint (graph_edit, point);
  738.     if (gn == 0)
  739.     return 0;
  740.  
  741.     BoxGraphNode* bgn = ptr_cast (BoxGraphNode, gn);
  742.     if (bgn == 0)
  743.     return 0;
  744.  
  745.     return disp_graph->get_nr (bgn);
  746. }
  747.  
  748.  
  749. //-----------------------------------------------------------------------------
  750. // Sensitivitaeten setzen
  751. //-----------------------------------------------------------------------------
  752.  
  753. void DataDisp::no_displaysHP (void*, void* , void* call_data)
  754. {
  755.     bool empty = bool(call_data);
  756.     if (!empty)
  757.     {
  758.     XtManageChild(graph_edit);
  759.     if (data_disp_shell)
  760.     {
  761.         static bool initial_popup = true;
  762.  
  763.         if (initial_popup)
  764.         {
  765.         initial_popup_shell(data_disp_shell);
  766.         initial_popup = false;
  767.         }
  768.     }
  769.     }
  770.  
  771.     set_sensitive (graph_popup[GraphItms::Refresh].widget,
  772.            (!empty && gdb->isReadyWithPrompt()));
  773. }
  774.  
  775. void DataDisp::source_argHP (void*, void* , void*)
  776. {
  777.     refresh_args();
  778. }
  779.  
  780. void DataDisp::graph_argHP (void*, void* , void*)
  781. {
  782.     refresh_args();
  783. }
  784.  
  785. void DataDisp::graph_unselectHP (void*, void*, void*)
  786. {
  787.     // Selection lost - clear all highlights
  788.     for (GraphNode *gn = disp_graph->firstNode();
  789.      gn != 0; gn = disp_graph->nextNode(gn))
  790.     {
  791.     BoxGraphNode *bgn = ptr_cast(BoxGraphNode, gn);
  792.     if (bgn && bgn->selected())
  793.     {
  794.         bgn->selected() = false;
  795.         graphEditRedrawNode(graph_edit, bgn);
  796.     }
  797.     }
  798.  
  799.     refresh_args();
  800.     fill_labels();
  801. }
  802.  
  803. void DataDisp::gdb_ready_for_questionHP (void*, void* , void*)
  804. {
  805.     refresh_args();
  806. }
  807.  
  808. //-----------------------------------------------------------------------------
  809. // Action procs
  810. //----------------------------------------------------------------------------
  811.  
  812. void DataDisp::graph_dereferenceAct (Widget w, XEvent*, String*, Cardinal*)
  813. {
  814.     dereferenceCB(w, 0, 0);
  815. }
  816.  
  817. void DataDisp::graph_detailAct (Widget w, XEvent*, String*, Cardinal*)
  818. {
  819.     toggleDetailCB(w, 0, 0);
  820. }
  821.  
  822. void DataDisp::graph_rotateAct (Widget w, XEvent*, String*, Cardinal*)
  823. {
  824.     toggleRotateCB(w, 0, 0);
  825. }
  826.  
  827. void DataDisp::graph_dependentAct (Widget w, XEvent*, String*, Cardinal*)
  828. {
  829.     dependentCB(w, 0, 0);
  830. }
  831.  
  832.  
  833. Time DataDisp::last_select_time = 0;
  834.  
  835. // The GraphEdit `select' action with some data display magic prepended
  836. void DataDisp::graph_selectAct (Widget w,
  837.                 XEvent* event,
  838.                 String* args,
  839.                 Cardinal* num_args)
  840. {
  841.     // Let multi-clicks pass right through
  842.     Time t = time(event);
  843.     if (Time(t - last_select_time) > Time(XtGetMultiClickTime(XtDisplay(w))))
  844.     set_args(point(event));
  845.     last_select_time = t;
  846.  
  847.     XtCallActionProc(graph_edit, "select", event, args, *num_args);
  848. }
  849.  
  850. // The GraphEdit `select-or-move' action with some data display magic prepended
  851. void DataDisp::graph_select_or_moveAct (Widget w,
  852.                     XEvent* event,
  853.                     String* args,
  854.                     Cardinal* num_args)
  855. {
  856.     // Let multi-clicks pass right through
  857.     Time t = time(event);
  858.     if (Time(t - last_select_time) > Time(XtGetMultiClickTime(XtDisplay(w))))
  859.     set_args(point(event));
  860.     last_select_time = t;
  861.  
  862.     XtCallActionProc(graph_edit, "select-or-move", event, args, *num_args);
  863. }
  864.  
  865. void DataDisp::graph_popupAct (Widget, XEvent* event, String*, Cardinal*)
  866. {
  867.     static BoxPoint* p = 0;
  868.     if (p == 0)
  869.     {
  870.     p = new BoxPoint;
  871.  
  872.     MMaddCallbacks(graph_popup, XtPointer(p));
  873.     MMaddCallbacks(node_popup,  XtPointer(p));
  874.     }
  875.     *p = point(event);
  876.  
  877.     set_args(*p);
  878.  
  879.     Widget popup = 0;
  880.     if (selected_node() == 0)
  881.     popup = graph_popup_w;
  882.     else
  883.     popup = node_popup_w;
  884.  
  885.     XmMenuPosition(popup, &event->xbutton);
  886.     XtManageChild(popup);
  887. }
  888.  
  889. void DataDisp::set_args(BoxPoint p)
  890. {
  891.     DispNode*  disp_node   = 0;
  892.     DispValue* disp_value  = 0;
  893.     BoxGraphNode *disp_bgn = 0;
  894.  
  895.     bool was_selected = false;
  896.  
  897.     int disp_nr = getDispNrAtPoint(p);
  898.     if (disp_nr)
  899.     {
  900.     disp_node = disp_graph->get (disp_nr);
  901.     disp_value = (DispValue *)disp_node->box()->data(p);
  902.         
  903.     disp_bgn = disp_node->nodeptr();
  904.     was_selected = disp_bgn->selected() && disp_value == 0;
  905.  
  906.     disp_node->select(disp_value);
  907.     graphEditRedrawNode(graph_edit, disp_bgn);
  908.     }
  909.  
  910.     // Clear other highlights and selections
  911.     MapRef ref;
  912.     for (DispNode* dn = disp_graph->first(ref); 
  913.      dn != 0;
  914.      dn = disp_graph->next(ref))
  915.     {
  916.     if (dn != disp_node)
  917.     {
  918.         BoxGraphNode *node = dn->nodeptr();
  919.         bool redraw = false;
  920.  
  921.         if (!was_selected)
  922.         {
  923.         redraw |= node->selected();
  924.         dn->nodeptr()->selected() = false;
  925.         }
  926.  
  927.         redraw |= (node->highlight() != 0);
  928.         dn->select(0);
  929.  
  930.         if (redraw)
  931.         graphEditRedrawNode(graph_edit, node);
  932.     }
  933.     }
  934.  
  935.     refresh_args();
  936.     fill_labels();
  937. }
  938.  
  939. DispNode *DataDisp::selected_node()
  940. {
  941.     DispNode *ret = 0;
  942.  
  943.     MapRef ref;
  944.     for (DispNode* dn = disp_graph->first(ref); 
  945.      dn != 0;
  946.      dn = disp_graph->next(ref))
  947.     {
  948.     if (dn->selected())
  949.     {
  950.         if (ret == 0)
  951.         ret = dn;
  952.         else
  953.         return 0;    // multiple nodes selected
  954.     }
  955.     }
  956.  
  957.     return ret;
  958. }
  959.  
  960. DispValue *DataDisp::selected_value()
  961. {
  962.     DispNode *dn = selected_node();
  963.     if (dn == 0)
  964.     return 0;
  965.  
  966.     DispValue *dv = dn->selected_value();
  967.     return dv ? dv : dn->value();
  968. }
  969.  
  970. void DataDisp::refresh_args()
  971. {
  972.     int count_selected           = 0;
  973.     int count_all                = 0;
  974.     int count_selected_disabled  = 0;
  975.     int count_selected_enabled   = 0;
  976.     int count_selected_expanded  = 0;
  977.     int count_selected_collapsed = 0;
  978.  
  979.     MapRef ref;
  980.     for (DispNode* dn = disp_graph->first(ref); 
  981.      dn != 0;
  982.      dn = disp_graph->next(ref))
  983.     {
  984.     count_all++;
  985.     if (dn->selected())
  986.     {
  987.         count_selected++;
  988.         if (dn->disabled())
  989.         count_selected_disabled++;
  990.         if (dn->enabled())
  991.         count_selected_enabled++;
  992.  
  993.         DispValue *dv = dn->selected_value();
  994.         if (dv == 0)
  995.         dv = dn->value();
  996.         if (dv)
  997.         {
  998.         if (dv->expanded())
  999.             count_selected_expanded++;
  1000.         if (dv->collapsed())
  1001.             count_selected_collapsed++;
  1002.         }
  1003.     }
  1004.     }
  1005.  
  1006.     if (count_selected > 0)
  1007.     {
  1008.     switch (gdb->type())
  1009.     {
  1010.     case DBX:
  1011.         // DBX cannot disable or enable displays
  1012.         count_selected_enabled = count_selected_disabled = 0;
  1013.         break;
  1014.  
  1015.     case GDB:
  1016.         break;
  1017.     }
  1018.     }
  1019.  
  1020.     if (count_selected > 1)
  1021.     {
  1022.     // Clear all local highlights
  1023.     MapRef ref;
  1024.     for (DispNode* dn = disp_graph->first(ref); 
  1025.          dn != 0;
  1026.          dn = disp_graph->next(ref))
  1027.     {
  1028.         BoxGraphNode *node = dn->nodeptr();
  1029.         bool redraw = (node->highlight() != 0);
  1030.  
  1031.         dn->select(0);
  1032.         if (redraw)
  1033.         graphEditRedrawNode(graph_edit, node);
  1034.     }
  1035.     }
  1036.  
  1037.     DispNode *disp_node_arg   = selected_node();
  1038.     DispValue *disp_value_arg = selected_value();
  1039.  
  1040.     Boolean gdb_ok = (gdb != 0 && gdb->isReadyWithPrompt());
  1041.  
  1042.     // New
  1043.     set_sensitive(graph_popup[GraphItms::New].widget,    gdb_ok);
  1044.     set_sensitive(display_area[DisplayItms::New].widget, gdb_ok);
  1045.  
  1046.     // New ()
  1047.     Boolean arg_ok = (gdb_ok && !source_arg->empty());
  1048.     set_sensitive(graph_popup[GraphItms::NewArg].widget, arg_ok);
  1049.  
  1050.     // Refresh (), Select All ()
  1051.     set_sensitive(graph_popup[GraphItms::Refresh].widget,   count_all);
  1052.     set_sensitive(graph_popup[GraphItms::SelectAll].widget, count_all);
  1053.  
  1054.     // Klick auf einen Knoten - - - - - - - - - - - - - - - - - - - - - - - -
  1055.     Boolean dereference_ok  = False;
  1056.     Boolean rotate_ok       = False;
  1057.     Boolean rotate_state    = False;
  1058.  
  1059.     if (disp_value_arg)
  1060.     {
  1061.     switch (disp_value_arg->type())
  1062.     {
  1063.     case Simple:
  1064.     case Reference:
  1065.         break;
  1066.  
  1067.     case Pointer: 
  1068.         dereference_ok = gdb_ok;
  1069.         break;
  1070.  
  1071.     case Array:
  1072.         rotate_ok     = disp_value_arg->expanded();
  1073.         rotate_state  = disp_value_arg->vertical_aligned();
  1074.         break;
  1075.  
  1076.     case StructOrClass:
  1077.     case BaseClass:
  1078.         break;
  1079.  
  1080.     default:
  1081.         // Falscher Fehler
  1082.         assert (0);
  1083.         break;
  1084.     }
  1085.     }
  1086.  
  1087.     // Dereference
  1088.     set_sensitive(node_popup[ValueItms::Dereference].widget,
  1089.           dereference_ok);
  1090.     set_sensitive(graph_cmd_area[ValueItms::Dereference].widget,
  1091.           dereference_ok);
  1092.     set_sensitive(display_area[DisplayItms::Dereference].widget,
  1093.           dereference_ok);
  1094.  
  1095.     // Dependent
  1096.     set_sensitive(graph_cmd_area[ValueItms::Dependent].widget, 
  1097.           count_selected == 1);
  1098.     set_sensitive(display_area[DisplayItms::Dependent].widget,
  1099.           count_selected == 1);
  1100.  
  1101.     // Rotate
  1102.     set_sensitive(node_popup[ValueItms::Rotate].widget,
  1103.           rotate_ok);
  1104.     set_sensitive(graph_cmd_area[ValueItms::Rotate].widget,
  1105.           rotate_ok);
  1106.  
  1107.     // Enable/Disable
  1108.     if (count_selected_enabled > 0 && count_selected_disabled == 0)
  1109.     {
  1110.     // Only disabled displays selected
  1111.     set_label(node_popup[ValueItms::Disable].widget, "Disable Display");
  1112.     set_label(graph_cmd_area[ValueItms::Disable].widget, "Disable ()");
  1113.     set_sensitive(node_popup[ValueItms::Disable].widget, true);
  1114.     set_sensitive(graph_cmd_area[ValueItms::Disable].widget, true);
  1115.     }
  1116.     else if (count_selected_disabled > 0 && count_selected_enabled == 0)
  1117.     {
  1118.     // Only enabled displays selected
  1119.     set_label(node_popup[ValueItms::Disable].widget, "Enable Display");
  1120.     set_label(graph_cmd_area[ValueItms::Disable].widget, "Enable ()");
  1121.     set_sensitive(node_popup[ValueItms::Disable].widget, true);
  1122.     set_sensitive(graph_cmd_area[ValueItms::Disable].widget, true);
  1123.     }
  1124.     else 
  1125.     {
  1126.     // Disabled as well as enabled displays selected
  1127.     set_sensitive(node_popup[ValueItms::Disable].widget, false);
  1128.     set_sensitive(graph_cmd_area[ValueItms::Disable].widget, false);
  1129.     }
  1130.  
  1131.     // Enable
  1132.     set_sensitive(display_area[DisplayItms::Enable].widget, 
  1133.           count_selected_disabled);
  1134.  
  1135.     // Disable
  1136.     set_sensitive(display_area[DisplayItms::Disable].widget, 
  1137.           count_selected_enabled);
  1138.  
  1139.     // Show/Hide Detail
  1140.     if (count_selected_expanded > 0 && count_selected_collapsed == 0)
  1141.     {
  1142.     // Only expanded displays selected
  1143.     set_label(node_popup[ValueItms::Detail].widget, "Hide Detail");
  1144.     set_label(graph_cmd_area[ValueItms::Detail].widget, "Hide ()");
  1145.     set_sensitive(node_popup[ValueItms::Detail].widget, true);
  1146.     set_sensitive(graph_cmd_area[ValueItms::Detail].widget, true);
  1147.     }
  1148.     else if (count_selected_expanded == 0 && count_selected_collapsed > 0)
  1149.     {
  1150.     // Only collapsed displays selected
  1151.     set_label(node_popup[ValueItms::Detail].widget, "Show Detail");
  1152.     set_label(graph_cmd_area[ValueItms::Detail].widget, "Show ()");
  1153.     set_sensitive(node_popup[ValueItms::Detail].widget, true);
  1154.     set_sensitive(graph_cmd_area[ValueItms::Detail].widget, true);
  1155.     }
  1156.     else
  1157.     {
  1158.     // Expanded as well as collapsed displays selected
  1159.     set_sensitive(node_popup[ValueItms::Detail].widget, false);
  1160.     set_sensitive(graph_cmd_area[ValueItms::Detail].widget, false);
  1161.     }
  1162.  
  1163.     set_sensitive(display_area[DisplayItms::ShowDetail].widget, 
  1164.           count_selected_collapsed);
  1165.     set_sensitive(display_area[DisplayItms::HideDetail].widget, 
  1166.           count_selected_expanded);
  1167.  
  1168.  
  1169.     // Delete
  1170.     set_sensitive(graph_cmd_area[ValueItms::Delete].widget,
  1171.           count_selected);
  1172.     set_sensitive(display_area[DisplayItms::Delete].widget, 
  1173.           count_selected);
  1174.  
  1175.     // Argument field
  1176.     if (count_selected > 0)
  1177.     {
  1178.     string arg;
  1179.     if (disp_value_arg)
  1180.         arg = disp_value_arg->full_name();
  1181.     else if (disp_node_arg)
  1182.         arg = disp_node_arg->name();
  1183.     else
  1184.     {
  1185.         ostrstream arg_os;
  1186.         arg_os << "(" << count_selected << " displays)";
  1187.         arg = arg_os;
  1188.     }
  1189.     graph_arg->set_string(arg);
  1190.  
  1191.     // Cause argument field to obtain the selection
  1192.     Widget w = graph_arg->widget();
  1193.     XmTextFieldSetSelection(w,
  1194.                 0, XmTextFieldGetLastPosition(w),
  1195.                 XtLastTimestampProcessed(XtDisplay(w)));
  1196.  
  1197.     // The value is already highlighted in the node -- 
  1198.     // hence, no need to cause confusion
  1199.     XmTextFieldSetHighlight(w,
  1200.                 0, XmTextFieldGetLastPosition(w),
  1201.                 XmHIGHLIGHT_NORMAL);
  1202.     }
  1203.     else
  1204.     {
  1205.     // No argument
  1206.     graph_arg->set_string("");
  1207.  
  1208.     // Clear selection
  1209.     Widget w = graph_arg->widget();
  1210.     XmTextFieldClearSelection(w, XtLastTimestampProcessed(XtDisplay(w)));
  1211.     }
  1212. }
  1213.  
  1214.  
  1215. // Update graph editor selection after a change in the display editor
  1216. void DataDisp::UpdateGraphEditorSelectionCB(Widget, XtPointer, XtPointer)
  1217. {
  1218.     // Avoid recursive and mutually recursive calls
  1219.     if (ignore_update_graph_editor_selection)
  1220.     return;
  1221.  
  1222.     ignore_update_graph_editor_selection   = true;
  1223.     ignore_update_display_editor_selection = true;
  1224.  
  1225.     int *display_nrs = getDisplayNumbers(display_list_w);
  1226.  
  1227.     // Update graph editor selection
  1228.     MapRef ref;
  1229.     for (DispNode *dn = disp_graph->first(ref); 
  1230.      dn != 0;
  1231.      dn = disp_graph->next(ref))
  1232.     {
  1233.     string nr = dn->disp_nr();
  1234.     int display_nr = get_positive_nr(nr);
  1235.  
  1236.     bool select = false;
  1237.     for (int i = 0; display_nrs[i] > 0; i++)
  1238.     {
  1239.         if (display_nr == display_nrs[i])
  1240.         {
  1241.         select = true;
  1242.         break;
  1243.         }
  1244.     }
  1245.  
  1246.     if (select != dn->selected())
  1247.     {
  1248.         dn->selected() = select;
  1249.         graphEditRedrawNode(graph_edit, dn->nodeptr());
  1250.     }
  1251.     }
  1252.  
  1253.     delete[] display_nrs;
  1254.  
  1255.     refresh_args();
  1256.  
  1257.     ignore_update_graph_editor_selection   = false;
  1258.     ignore_update_display_editor_selection = false;
  1259. }
  1260.  
  1261. // Update display editor selection after a change in the graph editor
  1262. void DataDisp::UpdateDisplayEditorSelectionCB(Widget, XtPointer, XtPointer)
  1263. {
  1264.     // Avoid recursive and mutually recursive calls
  1265.     if (ignore_update_display_editor_selection)
  1266.     return;
  1267.  
  1268.     ignore_update_graph_editor_selection   = true;
  1269.     ignore_update_display_editor_selection = true;
  1270.  
  1271.     refresh_args();
  1272.     fill_labels();
  1273.  
  1274.     ignore_update_graph_editor_selection  =  false;
  1275.     ignore_update_display_editor_selection = false;
  1276. }
  1277.  
  1278.  
  1279. //-----------------------------------------------------------------------
  1280. // Sorting nodes for layout
  1281. //-----------------------------------------------------------------------
  1282.  
  1283. void DataDisp::CompareNodesCB(Widget, XtPointer, XtPointer call_data)
  1284. {
  1285.     GraphEditCompareNodesInfo *info = (GraphEditCompareNodesInfo *)call_data;
  1286.  
  1287.     BoxGraphNode *node1 = ptr_cast(BoxGraphNode, info->node1);
  1288.     BoxGraphNode *node2 = ptr_cast(BoxGraphNode, info->node2);
  1289.  
  1290.     DispNode *disp1 = 0;
  1291.     DispNode *disp2 = 0;
  1292.  
  1293.     if (node1 && node2)
  1294.     {
  1295.     int nr1 = disp_graph->get_nr(node1);
  1296.     int nr2 = disp_graph->get_nr(node2);
  1297.  
  1298.     disp1 = disp_graph->get(nr1);
  1299.     disp2 = disp_graph->get(nr2);
  1300.     }
  1301.  
  1302.     if (disp1 && disp2)
  1303.     {
  1304.     string name1 = disp1->name();
  1305.     string name2 = disp2->name();
  1306.  
  1307.     char *p1 = (char *)name1;
  1308.     char *p2 = (char *)name2;
  1309.  
  1310.     while (*p1 && *p2 && *p1 == *p2)
  1311.         p1++, p2++;
  1312.  
  1313.     if (isdigit(*p1) && isdigit(*p2))
  1314.     {
  1315.         // Compare numerals numerically
  1316.         long i1 = strtol(p1, NULL, 0);
  1317.         long i2 = strtol(p2, NULL, 0);
  1318.  
  1319.         info->result = i1 - i2;
  1320.     }
  1321.     else
  1322.     {
  1323.         // Simple string comparison
  1324.         info->result = *p1 - *p2;
  1325.     }
  1326.     }
  1327.     else
  1328.     {
  1329.     if (disp1)
  1330.     {
  1331.         // Known nodes are ``larger'' than unknown nodes
  1332.         info->result = 1;
  1333.     }
  1334.     else if (disp2) 
  1335.     {
  1336.         // Known nodes are ``larger'' than unknown nodes
  1337.         info->result = -1;
  1338.     }
  1339.     else
  1340.     {
  1341.         // Comparing the pointer values will keep pointers constant
  1342.         info->result = long(info->node1) - long(info->node2);
  1343.     }
  1344.     }
  1345.  
  1346. #if LOG_COMPARE
  1347.     if (disp1 && disp2)
  1348.     {
  1349.     clog << "Comparing " << disp1->name() 
  1350.          << " and " << disp2->name() << " yields " << info->result << "\n";
  1351.     }
  1352.     else
  1353.     {
  1354.     clog << "Cannot compare: unknown nodes\n";
  1355.     }
  1356. #endif
  1357. }
  1358.  
  1359. //-----------------------------------------------------------------------
  1360. // Anfragen an gdb stellen und Antworten bearbeiten
  1361. //-----------------------------------------------------------------------
  1362.  
  1363. //-----------------------------------------------------------------------------
  1364. // Erzeugung von neuen (unabhaengigen) Displays
  1365. //-----------------------------------------------------------------------------
  1366.  
  1367. regex RXmore_than_one ("\\[[0-9]+\\.\\.[0-9]+\\]", true);
  1368.  
  1369. // ***************************************************************************
  1370. // sendet den Display-Befehl an den gdb
  1371. // wird ein Boxpoint uebergeben, so wird der neue Knoten dorthin gesetzt
  1372. // sonst an eine Default-Position.
  1373. //
  1374. void DataDisp::new_displaySQ (string display_expression, BoxPoint* p,
  1375.                   Widget origin)
  1376. {
  1377.     if (origin)
  1378.     last_origin = origin;
  1379.  
  1380.     if (display_expression == "")
  1381.     return;
  1382.     if (display_expression.contains (RXmore_than_one)) {
  1383.     new_displaysSQA (display_expression, p);
  1384.     return;
  1385.     }
  1386.  
  1387.     switch (gdb->type())
  1388.     {
  1389.     case GDB:
  1390.     {
  1391.     string cmd = gdb->display_command() + " " + display_expression;
  1392.     bool ok = gdb->send_question (cmd, new_displayOQC, p);
  1393.     if (!ok) {
  1394.         post_gdb_busy(last_origin);
  1395.     }
  1396.     }
  1397.     break;
  1398.  
  1399.     case DBX:
  1400.     {
  1401.     gdb_question(gdb->display_command() + " " + display_expression);
  1402.     string cmd = gdb->print_command() + " " + display_expression;
  1403.     bool ok = gdb->send_question (cmd, new_displayOQC, p);
  1404.     if (!ok) {
  1405.         post_gdb_busy(last_origin);
  1406.     }
  1407.     }
  1408.     break;
  1409.     }
  1410. }
  1411.  
  1412.  
  1413. DispNode *DataDisp::new_node (string& answer)
  1414. {
  1415.     string disp_nr_str;
  1416.     switch(gdb->type())
  1417.     {
  1418.     case GDB:
  1419.     disp_nr_str = read_disp_nr_str (answer, gdb->type());
  1420.     if (disp_nr_str == "")
  1421.         return 0;
  1422.     break;
  1423.  
  1424.     case DBX:
  1425.     // Assign a default number
  1426.     disp_nr_str = itostring(disp_graph->count_all() + 1);
  1427.     break;
  1428.     }
  1429.  
  1430.     string name = read_disp_name (answer, gdb->type());
  1431.     DispNode* dn = 0;
  1432.  
  1433.     if (is_disabling (answer, gdb->type()))
  1434.     {
  1435.     post_gdb_message (answer, last_origin);
  1436.     dn = new DispNode(disp_nr_str, name);
  1437.     }
  1438.     else
  1439.     {
  1440.     dn = new DispNode(disp_nr_str, name, answer);
  1441.     }
  1442.  
  1443.     return dn;
  1444. }
  1445.  
  1446.  
  1447. // ***************************************************************************
  1448. // erzeugt neuen Display-Knoten und setzt ihn an den im data-Argument
  1449. // angegebenen Punkt (falls (BoxPoint *)data != (-1,-1))
  1450. //
  1451. void DataDisp::new_displayOQC (const string& answer, void* data)
  1452. {
  1453.     if (answer == "") {
  1454.     // Problemfall bei Start mit core-file, display-Ausgabe nur bei
  1455.     // display-Befehl
  1456.     gdb->send_question (gdb->display_command(),
  1457.                 new_display_extraOQC,
  1458.                 data);
  1459.     }
  1460.     else if (!contains_display (answer, gdb->type())) {
  1461.     post_gdb_message (answer, last_origin);
  1462.     }
  1463.     else {
  1464.     // Unselect all nodes
  1465.     for (GraphNode *gn = disp_graph->firstNode();
  1466.          gn != 0; gn = disp_graph->nextNode(gn))
  1467.     {
  1468.         BoxGraphNode *bgn = ptr_cast(BoxGraphNode, gn);
  1469.         if (bgn)
  1470.         bgn->selected() = false;
  1471.     }
  1472.  
  1473.     // DispNode erzeugen und ggf. disabling-Meldung ausgeben
  1474.     string ans = answer;
  1475.     DispNode *dn = new_node(ans);
  1476.     if (dn == 0)
  1477.         return;
  1478.  
  1479.     // BoxPoint berechnen
  1480.     BoxPoint* p         = (BoxPoint *)data;
  1481.     BoxPoint  box_point =
  1482.         (p == 0 || *p == BoxPoint(-1,-1)) ?
  1483.         disp_graph->default_new_box_point(dn, graph_edit) :
  1484.         (*p);
  1485.     dn->moveTo(box_point);
  1486.     dn->selected() = true;
  1487.  
  1488.     // in den Graphen einfuegen
  1489.     string nr = dn->disp_nr();
  1490.     disp_graph->insert_new (get_positive_nr(nr), dn);
  1491.     refresh_graph_edit();
  1492.     }
  1493. }
  1494.  
  1495. // ***************************************************************************
  1496. // Aus den Display-Ausdruecken den ersten (neuen) herausfischen, und dann
  1497. // der normalen Verarbeitung zufuehren.
  1498. //
  1499. void DataDisp::new_display_extraOQC (const string& answer, void* data)
  1500. {
  1501.     string ans = answer;
  1502.     string display = read_next_display (ans, gdb->type());
  1503.     new_displayOQC (display, data);
  1504. }
  1505.  
  1506. // ***************************************************************************
  1507. // wird von new_displaySQ aufgerufen, wenn die display_expression die
  1508. // array-notation RXmore_than_one enthaelt.
  1509. //
  1510. void DataDisp::new_displaysSQA (string display_expression, BoxPoint* p)
  1511. {
  1512.     assert (display_expression.contains (RXmore_than_one));
  1513.  
  1514.     // einzelne display-Ausdruecke erzeugen und display-Befehle im array 
  1515.     // abschicken...
  1516.     string prefix = display_expression.before(RXmore_than_one);
  1517.     string postfix = display_expression.after(RXmore_than_one);
  1518.     string range = display_expression.from (RXmore_than_one);
  1519.     range.del("[");
  1520.     int start = get_nr(range);
  1521.     assert(start >= 0);
  1522.     range = range.after("..");
  1523.     int stop = get_nr (range);
  1524.     assert (stop >= start);
  1525.     int count = stop + 1 - start;
  1526.  
  1527.     string *display_cmds = new string[count];
  1528.     string *print_cmds   = new string[count];
  1529.  
  1530.     int j = 0;
  1531.     for (int i = start; i < stop + 1; i++) {
  1532.     display_cmds[j] = 
  1533.         gdb->display_command() + " " 
  1534.         + prefix + "[" + itostring (i) + "]" + postfix;
  1535.     print_cmds[j] = 
  1536.         gdb->print_command() + " "
  1537.         + prefix + "[" + itostring (i) + "]" + postfix;
  1538.     j++;
  1539.     }
  1540.  
  1541.     switch (gdb->type())
  1542.     {
  1543.     case GDB:
  1544.     {
  1545.     void** dummy = new void *[count];
  1546.     int k = gdb->send_qu_array (display_cmds,
  1547.                     dummy,
  1548.                     count,
  1549.                     new_displaysOQAC,
  1550.                     p);
  1551.     if (k == 0) {
  1552.         post_gdb_busy(last_origin);
  1553.     }
  1554.     delete[] dummy;
  1555.     }
  1556.     break;
  1557.  
  1558.     case DBX:
  1559.     {
  1560.     for (int i = 0; i < count; i++)
  1561.         gdb_question(display_cmds[i]);
  1562.  
  1563.     void** dummy = new void *[count];
  1564.     int k = gdb->send_qu_array (print_cmds,
  1565.                     dummy,
  1566.                     count,
  1567.                     new_displaysOQAC,
  1568.                     p);
  1569.     if (k == 0) {
  1570.         post_gdb_busy(last_origin);
  1571.     }
  1572.     delete[] dummy;
  1573.     }
  1574.     break;
  1575.     }
  1576.  
  1577.     delete[] display_cmds;
  1578.     delete[] print_cmds;
  1579. }
  1580.  
  1581. // ***************************************************************************
  1582. void DataDisp::new_displaysOQAC (string answers[],
  1583.                  void*  qu_datas[],
  1584.                  int    count,
  1585.                  void*  data)
  1586. {
  1587.     // Unselect all nodes
  1588.     for (GraphNode *gn = disp_graph->firstNode();
  1589.      gn != 0; gn = disp_graph->nextNode(gn))
  1590.     {
  1591.     BoxGraphNode *bgn = ptr_cast(BoxGraphNode, gn);
  1592.     if (bgn)
  1593.         bgn->selected() = false;
  1594.     }
  1595.  
  1596.     // Create and select new nodes
  1597.     for (int i = 0; i < count; i++) {
  1598.     if (!contains_display (answers[i], gdb->type()))
  1599.         post_gdb_message (answers[i], last_origin);
  1600.     else {
  1601.  
  1602.         // DispNode erzeugen und ggf. disabling-Meldung merken
  1603.         DispNode *dn = new_node(answers[i]);
  1604.         if (dn == 0)
  1605.         return;
  1606.  
  1607.         BoxPoint* p = (BoxPoint *) data;
  1608.         BoxPoint  box_point =
  1609.         (p == 0 || *p == BoxPoint(-1,-1)) ?
  1610.         disp_graph->default_new_box_point(dn, graph_edit) :
  1611.         (*p);
  1612.  
  1613.         dn->moveTo(box_point);
  1614.         dn->selected() = true;
  1615.  
  1616.         // Insert into graph
  1617.         string nr = dn->disp_nr();
  1618.         disp_graph->insert_new (get_positive_nr(nr), dn);
  1619.     }
  1620.     }
  1621.     delete[] answers;
  1622.     delete[] qu_datas;
  1623.  
  1624.     refresh_graph_edit();
  1625. }
  1626.  
  1627.  
  1628. //-----------------------------------------------------------------------------
  1629. // Den disp-graph auf aktuellen Stand bringen.
  1630. //-----------------------------------------------------------------------------
  1631.  
  1632. // ***************************************************************************
  1633. // sendet den Befehl "display" an den gdb,
  1634. // um Displays zu aktualisieren. (kein Loeschen von Displays)
  1635. //
  1636. void DataDisp::refresh_displaySQ () 
  1637. {
  1638.     bool ok = false;
  1639.  
  1640.     switch (gdb->type())
  1641.     {
  1642.     case GDB:
  1643.     ok = gdb->send_question(gdb->display_command(), refresh_displayOQC, 0);
  1644.     break;
  1645.  
  1646.     case DBX:
  1647.     // No way to do this in DBX.
  1648.     // (We may issue a `print' command for every display shown.  FIXME)
  1649.     ok = false;
  1650.     break;
  1651.     }
  1652.  
  1653.     if (!ok)
  1654.     {
  1655.     // Don't complain; simply redraw display.
  1656.     refresh_graph_edit();
  1657.     }
  1658. }
  1659.  
  1660. // ***************************************************************************
  1661. // Aktualisiert die Displays entsprechend.
  1662. //
  1663. void DataDisp::refresh_displayOQC (const string& answer, void *)
  1664. {
  1665.     bool disabling_occurred;
  1666.  
  1667.     string ans = answer;
  1668.  
  1669.     // Antwort auf 'display' auswerten
  1670.     string not_my_displays = process_displays (ans, disabling_occurred);
  1671.  
  1672.     // Bei Fehlermeldung (Disabling...) nochmal refresh.
  1673.     if (disabling_occurred) {
  1674.     refresh_displaySQ();
  1675.     }
  1676.     else {
  1677.     refresh_graph_edit();
  1678.     }
  1679. }
  1680.  
  1681. // ***************************************************************************
  1682. // sendet die Befehle "info display" und "display" an den gdb,
  1683. // um Displays zu aktualisieren.
  1684. //
  1685. void DataDisp::refresh_displaySQA (Widget origin)
  1686. {
  1687.     if (origin)
  1688.     last_origin = origin;
  1689.  
  1690.     string cmds[2];
  1691.     void*  dummy[2];
  1692.     bool ok = false;
  1693.  
  1694.     switch (gdb->type())
  1695.     {
  1696.     case GDB:
  1697.     cmds[0] = "info display";
  1698.     cmds[1] = gdb->display_command();
  1699.     ok = gdb->send_qu_array(cmds, dummy, 2, refresh_displayOQAC, 0);
  1700.     break;
  1701.  
  1702.     case DBX:
  1703.     // No way to do this in DBX.
  1704.     // (We may issue a `print' command for every display shown.  FIXME)
  1705.     ok = false;
  1706.     break;
  1707.     }
  1708.  
  1709.     if (!ok)
  1710.     {
  1711.     // Don't complain; simply redraw display.
  1712.     refresh_graph_edit();
  1713.     }
  1714. }
  1715.  
  1716. // ***************************************************************************
  1717. // Aktualisiert die Displays entsprechend.
  1718. //
  1719. void DataDisp::refresh_displayOQAC (string answers[],
  1720.                     void*  qu_datas[],
  1721.                     int    count,
  1722.                     void*  )
  1723. {
  1724.     if (count >= 1)
  1725.     {
  1726.     // Antwort auf 'info display' auswerten (evtl displays loeschen)
  1727.     process_info_display (answers[0]);
  1728.     }
  1729.     
  1730.     // Antwort auf 'display' auswerten
  1731.     bool disabling_occurred = false;
  1732.  
  1733.     if (count >= 2)
  1734.     {
  1735.     process_displays (answers[1], disabling_occurred);
  1736.     }
  1737.  
  1738.     delete[]answers;
  1739.     delete[]qu_datas;
  1740.  
  1741.     // Bei Fehlermeldung (Disabling...) nochmal refresh.
  1742.     if (disabling_occurred)
  1743.     {
  1744.     refresh_displaySQ();
  1745.     }
  1746. }
  1747.  
  1748.  
  1749.  
  1750. //-----------------------------------------------------------------------------
  1751. // Displays ausschalten (disable)
  1752. //-----------------------------------------------------------------------------
  1753.  
  1754. // ***************************************************************************
  1755. // sendet den 'disable display'-Befehl mit den Nummern an den gdb
  1756. // und aktualisiert den disp_graph.
  1757. //
  1758. void DataDisp::disable_displaySQ (int display_nrs[], int count)
  1759. {
  1760.     if (count == 0)
  1761.     return;
  1762.  
  1763.     int j;
  1764.     string cmd = "disable display ";
  1765.     for (j = 0; j < count; j++) {
  1766.     cmd += " " + itostring(display_nrs[j]);
  1767.     }
  1768.     bool ok = gdb->send_question (cmd, disable_displayOQC, 0);
  1769.     if (!ok)
  1770.     post_gdb_busy(last_origin);
  1771.     else {
  1772.     for (j = 0; j < count; j++) {
  1773.         disp_graph->get(display_nrs[j])->disable();
  1774.     }
  1775.     refresh_graph_edit();
  1776.     }
  1777. }
  1778.  
  1779.  
  1780. // ***************************************************************************
  1781. // Bei nicht-leerer Antwort Ausgabe als Fehlermeldung.
  1782. //
  1783. void DataDisp::disable_displayOQC (const string& answer, void *)
  1784. {
  1785.     if (answer != "")
  1786.     post_gdb_message (answer, last_origin);
  1787. }
  1788.  
  1789.  
  1790. //-----------------------------------------------------------------------------
  1791. // Displays einschalten (enable)
  1792. //-----------------------------------------------------------------------------
  1793.  
  1794. // ***************************************************************************
  1795. // sendet den 'enable display'-Befehl mit den Nummern an den gdb
  1796. // und aktualisiert den disp_graph.
  1797. //
  1798. void DataDisp::enable_displaySQ (int display_nrs[], int count)
  1799. {
  1800.     if (count == 0)
  1801.     return;
  1802.  
  1803.     int j;
  1804.     string cmd = "enable display";
  1805.     for (j = 0; j < count; j++) {
  1806.     cmd += " " + itostring(display_nrs[j]);
  1807.     }
  1808.     bool ok = gdb->send_question (cmd, enable_displayOQC, 0);
  1809.     if (!ok)
  1810.        post_gdb_busy(last_origin);
  1811. }
  1812.  
  1813.  
  1814. // ***************************************************************************
  1815. // Bei nicht-leerer Antwort Ausgabe als Fehlermeldung.
  1816. //
  1817. void DataDisp::enable_displayOQC (const string& answer, void *)
  1818. {
  1819.     if (answer != "")
  1820.     post_gdb_message (answer, last_origin);
  1821.  
  1822.     refresh_displaySQ ();
  1823. }
  1824.  
  1825.  
  1826. //-----------------------------------------------------------------------------
  1827. // Displays loeschen (delete)
  1828. //-----------------------------------------------------------------------------
  1829.  
  1830. // ***************************************************************************
  1831. // sendet den 'delete display'-Befehl mit den Nummern an den gdb
  1832. // und aktualisiert den disp_graph.
  1833. //
  1834. void DataDisp::delete_displaySQ (int display_nrs[], int count)
  1835. {
  1836.     if (count == 0)
  1837.     return;
  1838.  
  1839.     int j;
  1840.     string cmd = "undisplay ";
  1841.  
  1842.     switch (gdb->type())
  1843.     {
  1844.     case GDB:
  1845.     for (j = 0; j < count; j++)
  1846.     {
  1847.         cmd += " " + itostring(display_nrs[j]);
  1848.     }
  1849.     break;
  1850.  
  1851.     case DBX:
  1852.     int c = 0;
  1853.     for (j = 0; j < count; j++)
  1854.     {
  1855.         DispNode *dn = disp_graph->get(display_nrs[j]);
  1856.         if (dn)
  1857.         {
  1858.         if (c++)
  1859.             cmd += ", ";
  1860.         cmd += " " + dn->name();
  1861.         }
  1862.     }
  1863.     break;
  1864.     }
  1865.     
  1866.     bool ok = gdb->send_question (cmd, delete_displayOQC, 0);
  1867.     if (!ok)
  1868.     post_gdb_busy(last_origin);
  1869.     else {
  1870.     for (j = 0; j < count; j++) {
  1871.         disp_graph->del (display_nrs[j]);
  1872.     }
  1873.     // refresh_graph_edit();
  1874.     }
  1875. }
  1876.  
  1877.  
  1878. // ***************************************************************************
  1879. // Bei nicht-leerer Antwort Ausgabe als Fehlermeldung.
  1880. //
  1881. void DataDisp::delete_displayOQC (const string& answer, void *)
  1882. {
  1883.     string ans = answer;
  1884.  
  1885.     switch (gdb->type())
  1886.     {
  1887.     case GDB:
  1888.     break;
  1889.  
  1890.     case DBX:
  1891.     // Upon `undisplay', DBX redisplays remaining displays with
  1892.     // values
  1893.     if (answer != "")
  1894.     {
  1895.         bool disabling_occurred;
  1896.         process_displays(ans, disabling_occurred);
  1897.     }
  1898.     break;
  1899.     }
  1900.  
  1901.     // Anything remaining is an error message
  1902.     if (answer != "")
  1903.     post_gdb_message (ans, last_origin);
  1904. }
  1905.  
  1906.  
  1907. //-----------------------------------------------------------------------------
  1908. // Neue abhaengige Displays erzeugen
  1909. //-----------------------------------------------------------------------------
  1910.  
  1911. // ***************************************************************************
  1912. // sendet den Display-Befehl an den gdb (mit disp_nr als data).
  1913. //
  1914. void DataDisp::dependent_displaySQ (string display_expression, int disp_nr)
  1915. {
  1916.     if (display_expression == "")
  1917.     return;
  1918.     if (display_expression.contains (RXmore_than_one)) {
  1919.     dependent_displaysSQA (display_expression, disp_nr);
  1920.     return;
  1921.     }
  1922.  
  1923.     switch (gdb->type())
  1924.     {
  1925.     case GDB:
  1926.     {
  1927.     string cmd = gdb->display_command() + " " + display_expression;
  1928.     bool ok = gdb->send_question(cmd, dependent_displayOQC, 
  1929.                      (void *) disp_nr);
  1930.     if (!ok) {
  1931.         post_gdb_busy(last_origin);
  1932.     }
  1933.     }
  1934.     break;
  1935.  
  1936.     case DBX:
  1937.     {
  1938.     gdb_question(gdb->display_command() + " " + display_expression);
  1939.     string cmd = gdb->print_command() + " " + display_expression;
  1940.     bool ok = gdb->send_question(cmd, dependent_displayOQC, 
  1941.                    (void *) disp_nr);
  1942.     if (!ok) {
  1943.         post_gdb_busy(last_origin);
  1944.     }
  1945.     }
  1946.     break;
  1947.     }
  1948. }
  1949.  
  1950. // ***************************************************************************
  1951. // ruft disp_graph->insert_dependent (answer, data).
  1952. //
  1953. void DataDisp::dependent_displayOQC (const string& answer, void* data)
  1954. {
  1955.     if (answer == "") {
  1956.     // Problemfall bei Start mit core-file, display-Ausgabe nur bei
  1957.     // display-Befehl
  1958.     gdb->send_question
  1959.         (gdb->display_command(), dependent_display_extraOQC, data);
  1960.     }
  1961.     else if (!contains_display (answer, gdb->type())) {
  1962.     post_gdb_message (answer, last_origin);
  1963.     }
  1964.     else {
  1965.     string ans = answer;
  1966.  
  1967.     // Unselect all nodes
  1968.     for (GraphNode *gn = disp_graph->firstNode();
  1969.          gn != 0; gn = disp_graph->nextNode(gn))
  1970.     {
  1971.         BoxGraphNode *bgn = ptr_cast(BoxGraphNode, gn);
  1972.         if (bgn)
  1973.         bgn->selected() = false;
  1974.     }
  1975.  
  1976.     // DispNode erzeugen und ggf. disabling-Meldung merken
  1977.     DispNode *dn = new_node(ans);
  1978.     if (dn == 0)
  1979.         return;
  1980.  
  1981.     int old_disp_nr = int (data);
  1982.     BoxPoint box_point =
  1983.         disp_graph->default_dependent_box_point(dn, 
  1984.                             graph_edit, old_disp_nr);
  1985.     dn->moveTo(box_point);
  1986.     dn->selected() = true;
  1987.  
  1988.     // in den Graphen einfuegen
  1989.     string nr = dn->disp_nr();
  1990.     disp_graph->insert_dependent (get_positive_nr(nr), dn, old_disp_nr);
  1991.     refresh_graph_edit();
  1992.     }
  1993. }
  1994.  
  1995. // ***************************************************************************
  1996. // Aus den Display-Ausdruecken den ersten (neuen) herausfischen, und dann
  1997. // der normalen Verarbeitung zufuehren.
  1998. //
  1999. void DataDisp::dependent_display_extraOQC (const string& answer, void* data)
  2000. {
  2001.     string ans = answer;
  2002.     string display = read_next_display (ans, gdb->type());
  2003.     dependent_displayOQC (display, data);
  2004. }
  2005.  
  2006. // ***************************************************************************
  2007. // wird von dependent_displaySQ aufgerufen, wenn die display_expression die
  2008. // array-notation RXmore_than_one enthaelt.
  2009. //
  2010. void DataDisp::dependent_displaysSQA (string display_expression,
  2011.                       int disp_nr)
  2012. {
  2013.     assert (display_expression.contains (RXmore_than_one));
  2014.  
  2015.     // einzelne display-Ausdruecke erzeugen und display-Befehle im array 
  2016.     // abschicken...
  2017.     string prefix = display_expression.before(RXmore_than_one);
  2018.     string postfix = display_expression.after(RXmore_than_one);
  2019.     string range = display_expression.from (RXmore_than_one);
  2020.     range.del("[");
  2021.     int start = get_nr(range);
  2022.     assert(start >= 0);
  2023.     range = range.after("..");
  2024.     int stop = get_nr (range);
  2025.     assert (stop >= start);
  2026.     int count = stop + 1 - start;
  2027.  
  2028.     string *display_cmds = new string[count];
  2029.     string *print_cmds   = new string[count];
  2030.  
  2031.     int j = 0;
  2032.     for (int i = start; i < stop + 1; i++) {
  2033.     display_cmds[j] = 
  2034.         gdb->display_command() + " "
  2035.         + prefix + "[" + itostring (i) + "]" + postfix;
  2036.     print_cmds[j] = 
  2037.         gdb->print_command() + " " 
  2038.         + prefix + "[" + itostring (i) + "]" + postfix;
  2039.     j++;
  2040.     }
  2041.  
  2042.     switch (gdb->type())
  2043.     {
  2044.     case GDB:
  2045.     {
  2046.     void** dummy = new void *[count];
  2047.     int k = gdb->send_qu_array (display_cmds,
  2048.                     dummy,
  2049.                     count,
  2050.                     dependent_displaysOQAC,
  2051.                     (void *)disp_nr);
  2052.     if (k == 0) {
  2053.         post_gdb_busy(last_origin);
  2054.     }
  2055.     delete[] dummy;
  2056.     }
  2057.     break;
  2058.  
  2059.     case DBX:
  2060.     {
  2061.     for (int i = 0; i < count; i++)
  2062.         gdb_question(display_cmds[i]);
  2063.     void** dummy = new void *[count];
  2064.     int k = gdb->send_qu_array (print_cmds,
  2065.                     dummy,
  2066.                     count,
  2067.                     dependent_displaysOQAC,
  2068.                     (void *)disp_nr);
  2069.     if (k == 0) {
  2070.         post_gdb_busy(last_origin);
  2071.     }
  2072.     delete[] dummy;
  2073.     }
  2074.     break;
  2075.     }
  2076.  
  2077.     delete[] display_cmds;
  2078.     delete[] print_cmds;
  2079. }
  2080.  
  2081. // ***************************************************************************
  2082. void DataDisp::dependent_displaysOQAC (string answers[],
  2083.                        void*  qu_datas[],
  2084.                        int    count,
  2085.                        void*  data)
  2086. {
  2087.     int       old_disp_nr = int (data);
  2088.     string    name;
  2089.     DispNode* dn = 0;
  2090.  
  2091.     string disabling_error_msgs = "";
  2092.  
  2093.     // Unselect all nodes
  2094.     for (GraphNode *gn = disp_graph->firstNode();
  2095.      gn != 0; gn = disp_graph->nextNode(gn))
  2096.     {
  2097.     BoxGraphNode *bgn = ptr_cast(BoxGraphNode, gn);
  2098.     if (bgn)
  2099.         bgn->selected() = false;
  2100.     }
  2101.  
  2102.     for (int i = 0; i < count; i++) {
  2103.     if (!contains_display (answers[i], gdb->type()))
  2104.         post_gdb_message (answers[i], last_origin);
  2105.     else {
  2106.         // DispNode erzeugen und ggf. disabling-Meldung ausgeben
  2107.         string disp_nr_str;
  2108.  
  2109.         switch(gdb->type())
  2110.         {
  2111.         case GDB:
  2112.         disp_nr_str = read_disp_nr_str (answers[i], gdb->type());
  2113.         if (disp_nr_str == "")
  2114.             return;
  2115.         break;
  2116.  
  2117.         case DBX:
  2118.         // Assign a default number
  2119.         disp_nr_str = itostring(disp_graph->count_all() + 1);
  2120.         break;
  2121.         }
  2122.  
  2123.         name = read_disp_name (answers[i], gdb->type());
  2124.         if (is_disabling (answers[i], gdb->type()))
  2125.         {
  2126.         disabling_error_msgs += answers[i];
  2127.         dn = new DispNode(disp_nr_str, name);
  2128.         }
  2129.         else
  2130.         {
  2131.         dn = new DispNode(disp_nr_str, name, answers[i]);
  2132.         }
  2133.  
  2134.         BoxPoint box_point =
  2135.         disp_graph->default_dependent_box_point(dn, 
  2136.                             graph_edit, 
  2137.                             old_disp_nr);
  2138.  
  2139.         dn->moveTo(box_point);
  2140.         dn->selected() = true;
  2141.  
  2142.         // in den Graphen einfuegen
  2143.         string nr = dn->disp_nr();
  2144.         disp_graph->insert_dependent(get_positive_nr(nr), dn, old_disp_nr);
  2145.     }
  2146.     }
  2147.  
  2148.     delete[] answers;
  2149.     delete[] qu_datas;
  2150.  
  2151.     if ( disabling_error_msgs != "")
  2152.     post_gdb_message (disabling_error_msgs, last_origin);
  2153.  
  2154.     refresh_graph_edit();
  2155. }
  2156.  
  2157.  
  2158. //-----------------------------------------------------------------------------
  2159. // 'info display'-Ausgabe verarbeiten 
  2160. //-----------------------------------------------------------------------------
  2161.  
  2162. // ***************************************************************************
  2163. void DataDisp::process_info_display (string& info_display_answer)
  2164. {
  2165.     // Antwort auf 'info display' auswerten (evtl displays loeschen)
  2166.     // Fremde Display-Infos rausschneiden, eigene speichern
  2167.  
  2168.     int disp_nr;
  2169.     Map <int, string> info_disp_string_map;
  2170.     string *strptr;
  2171.  
  2172.     string next_disp_info = 
  2173.     read_first_disp_info (info_display_answer, gdb->type());
  2174.     while (next_disp_info != "")
  2175.     {
  2176.     disp_nr = get_positive_nr (next_disp_info);
  2177.     if (disp_nr >= 0)
  2178.     {
  2179.         if (disp_graph->contains(disp_nr)) 
  2180.         {
  2181.         // Eigenes display-info
  2182.         strptr = 
  2183.             new string(get_info_disp_str(next_disp_info, gdb->type()));
  2184.         info_disp_string_map.insert (disp_nr, strptr);
  2185.         }
  2186.     }
  2187.     next_disp_info = 
  2188.         read_next_disp_info(info_display_answer, gdb->type());
  2189.     }
  2190.  
  2191.  
  2192.     // Eigene Display-Infos verarbeiten
  2193.     bool changed = false;
  2194.     MapRef ref;
  2195.     for (int k = disp_graph->first_nr(ref); 
  2196.          k != 0 ; 
  2197.          k = disp_graph->next_nr(ref))
  2198.     {
  2199.     if (!info_disp_string_map.contains (k))
  2200.     {
  2201.         // Knoten loeschen
  2202.         disp_graph->del (k);
  2203.         changed = true;
  2204.     }
  2205.     else
  2206.     {
  2207.         // Knoten aktualisieren
  2208.         DispNode* dn = disp_graph->get (k);
  2209.         if (disp_is_disabled(*(info_disp_string_map.get (k)), gdb->type()))
  2210.         {
  2211.         if (dn->enabled())
  2212.         {
  2213.             dn->disable();
  2214.             changed = true;
  2215.         }
  2216.         }
  2217.         else
  2218.         {
  2219.         if (dn->disabled())
  2220.         {
  2221.             changed = true;
  2222.         }
  2223.         }
  2224.  
  2225.         delete info_disp_string_map.get (k);
  2226.         info_disp_string_map.del (k);
  2227.     }
  2228.     }
  2229.  
  2230.     assert (info_disp_string_map.length() == 0); // alles verarbeitet ?
  2231.     if (changed)
  2232.     refresh_graph_edit();
  2233.  
  2234.     fill_labels();
  2235. }
  2236.  
  2237.  
  2238.  
  2239. //-----------------------------------------------------------------------------
  2240. // Display-Ausgabe verarbeiten 
  2241. //-----------------------------------------------------------------------------
  2242.  
  2243. // ***************************************************************************
  2244. string DataDisp::process_displays (string& displays,
  2245.                    bool& disabling_occurred)
  2246. {
  2247.     Delay d;
  2248.  
  2249.     string not_my_displays;
  2250.     static string disabling_error_msgs;
  2251.     disabling_occurred = false;
  2252.  
  2253.     // Fremde Displays rausschneiden, eigene speichern
  2254.     int    disp_nr = 0;
  2255.     Map <int, string> disp_string_map;
  2256.     string *strptr;
  2257.  
  2258. #if LOG_DISPLAYS
  2259.     clog << "Processing displays " << quote(displays) << "...\n";
  2260. #endif
  2261.  
  2262.     string next_display = read_next_display (displays, gdb->type());
  2263.     while (next_display != "") 
  2264.     {
  2265. #if LOG_DISPLAYS
  2266.         clog << "Processing display " << quote(next_display);
  2267. #endif
  2268.     switch (gdb->type())
  2269.     {
  2270.     case GDB:
  2271.         disp_nr = get_positive_nr (next_display);
  2272.         break;
  2273.  
  2274.     case DBX:
  2275.     {
  2276.         disp_nr = 0;
  2277.         string disp_name = next_display;
  2278.         disp_name = read_disp_name(disp_name, gdb->type());
  2279.         MapRef ref;
  2280.         for (DispNode* dn = disp_graph->first(ref); 
  2281.          dn != 0;
  2282.          dn = disp_graph->next(ref))
  2283.         {
  2284.         if (dn->name() == disp_name)
  2285.         {
  2286.             string nr = dn->disp_nr();
  2287.             disp_nr = get_positive_nr(nr);
  2288.             break;
  2289.         }
  2290.         }
  2291.     }
  2292.     }
  2293.  
  2294. #if LOG_DISPLAYS
  2295.     clog << " (number " << disp_nr << ")\n";
  2296. #endif
  2297.  
  2298.     // Falls Fehlermeldung: merken und alles nochmal von vorne.
  2299.     if (is_disabling (next_display, gdb->type())) 
  2300.     {
  2301.         disabling_occurred = true;
  2302.         if (disp_nr >= 0 && disp_graph->contains(disp_nr))
  2303.         {
  2304.         disabling_error_msgs += 
  2305.             get_disp_value_str(next_display, gdb->type());
  2306.         }
  2307.         else
  2308.         {
  2309.         not_my_displays = next_display; //nur diesen merken
  2310.         }
  2311.  
  2312.         // disp_string_map leeren
  2313.         disp_string_map.delete_all_contents();
  2314.  
  2315.         return not_my_displays;
  2316.     }
  2317.  
  2318.     if (is_not_active (next_display, gdb->type()))
  2319.     {
  2320.         // Display is not active: don't insert it into map.
  2321.         // This way, it will be shown as disabled.
  2322.     }
  2323.     else if (disp_nr >= 0 && disp_graph->contains(disp_nr))
  2324.     {
  2325.         strptr = new string(get_disp_value_str(next_display, gdb->type()));
  2326.         disp_string_map.insert (disp_nr, strptr);
  2327.     }
  2328.     else 
  2329.     {
  2330.         not_my_displays += next_display + '\n';
  2331.     }
  2332.  
  2333.     next_display = read_next_display (displays, gdb->type());
  2334.     }
  2335.  
  2336.     // gesammelte Fehlermeldungen ausgeben.
  2337.     if ( !disabling_occurred && disabling_error_msgs != "") {
  2338.     post_gdb_message (disabling_error_msgs, last_origin);
  2339.     disabling_error_msgs = "";
  2340.     }
  2341.  
  2342.     // eigene Displays verarbeiten
  2343.     bool changed = false;
  2344.     MapRef ref;
  2345.     for (int k = disp_graph->first_nr(ref); 
  2346.          k != 0 ; 
  2347.          k = disp_graph->next_nr(ref)) {
  2348.     DispNode* dn = disp_graph->get(k);
  2349.  
  2350.     if (!disp_string_map.contains (k)) {
  2351.         // Knoten auf disabled setzen, falls nicht schon geschehen
  2352.         if (dn->enabled()) {
  2353.         dn->disable();
  2354.         changed = true;
  2355.         }
  2356.     }
  2357.     else {
  2358.         // Knoten aktualisieren
  2359.         strptr = disp_string_map.get(k);
  2360.         if ( dn->update (*strptr ))
  2361.         changed = true;
  2362.         if ( (*strptr != "") && !(strptr->matches (rxwhite)) ) {
  2363.         // hinter dem Display stand noch etwas, was nicht dazu gehoert
  2364.         // z.B. der return Wert bei finish
  2365.         not_my_displays += strptr->after (rxwhite);
  2366.         }
  2367.         delete disp_string_map.get(k);
  2368.         disp_string_map.del (k);
  2369.     }
  2370.     }
  2371.     assert (disp_string_map.length() == 0);
  2372.     if (changed) 
  2373.     refresh_graph_edit();
  2374.  
  2375.     return not_my_displays;
  2376. }
  2377.  
  2378.  
  2379.  
  2380. //----------------------------------------------------------------------------
  2381. // Display Editor
  2382. //----------------------------------------------------------------------------
  2383.  
  2384. // Sort LABELS and SELECTED
  2385. static void sort(string labels[], bool selected[], int size)
  2386. {
  2387.     // Shell sort -- simple and fast
  2388.     int h = 1;
  2389.     do {
  2390.     h = h * 3 + 1;
  2391.     } while (h <= size);
  2392.     do {
  2393.     h /= 3;
  2394.     for (int i = h; i < size; i++)
  2395.     {
  2396.         string v = labels[i];
  2397.         bool   b = selected[i];
  2398.         int    j;
  2399.         for (j = i; 
  2400.          j >= h && get_positive_nr(labels[j - h]) > get_positive_nr(v);
  2401.          j -= h)
  2402.         {
  2403.         labels[j]   = labels[j - h];
  2404.         selected[j] = selected[j - h];
  2405.         }
  2406.         if (i != j)
  2407.         {
  2408.         labels[j]   = v;
  2409.         selected[j] = b;
  2410.         }
  2411.     }
  2412.     } while (h != 1);
  2413. }
  2414.  
  2415. // Create labels for the list
  2416. void DataDisp::fill_labels()
  2417. {
  2418.     if (display_list_w == 0)
  2419.     return;
  2420.  
  2421.     int max_count      = disp_graph->count_all();
  2422.     string *label_list = new string[max_count + 1];
  2423.     bool *selected     = new bool[max_count + 1];
  2424.  
  2425.     int count = 0;
  2426.     label_list[count] = 
  2427.     (max_count > 0) ? "Num Enb Expression" : "No displays.";
  2428.     selected[count]   = false;
  2429.     count++;
  2430.  
  2431.     MapRef ref;
  2432.     for (int k = disp_graph->first_nr(ref); 
  2433.      k != 0 ; 
  2434.      k = disp_graph->next_nr(ref))
  2435.     {
  2436.     ostrstream os;
  2437.  
  2438.     string num = itostring(k) + ":     ";
  2439.     os << num.through(3);
  2440.  
  2441.     DispNode* dn = disp_graph->get(k);
  2442.     if (dn->enabled())
  2443.         os << "y";
  2444.     else
  2445.         os << "n";
  2446.     os << "   " << dn->name();
  2447.  
  2448.     label_list[count] = os;
  2449.     selected[count]   = dn->selected();
  2450.     count++;
  2451.     }
  2452.  
  2453.     sort(label_list + 1, selected + 1, count - 1);
  2454.  
  2455.     ignore_update_graph_editor_selection = true;
  2456.     setLabelList(display_list_w, label_list, selected, count);
  2457.     ignore_update_graph_editor_selection = false;
  2458.     
  2459.     delete[] label_list;
  2460.     delete[] selected;
  2461. }
  2462.  
  2463.  
  2464. void DataDisp::EditDisplaysCB(Widget, XtPointer, XtPointer)
  2465. {
  2466.     XtManageChild(edit_displays_dialog_w);
  2467. }
  2468.  
  2469.  
  2470. //----------------------------------------------------------------------------
  2471. // Constructor
  2472. //----------------------------------------------------------------------------
  2473. DataDisp::DataDisp (XtAppContext app_context,
  2474.             Widget parent,
  2475.             String /* vslpath */,
  2476.             String vslLibrary,
  2477.             int    max_name_length,
  2478.             bool   panned)
  2479. {
  2480.     registerOwnConverters();
  2481.  
  2482.     StringBox::fontTable     = new FontTable (XtDisplay(parent));
  2483.     DispBox::vsllib_name     = vslLibrary;
  2484.     DispBox::max_name_length = max_name_length;
  2485.  
  2486.     disp_graph = new DispGraph();
  2487.  
  2488.     disp_graph->addHandler(DispGraph_Empty, no_displaysHP);
  2489.  
  2490.     Arg args[10];
  2491.     int arg = 0;
  2492.     XtSetArg (args[arg], XtNgraph, (Graph *)disp_graph); arg++;
  2493.  
  2494.     if (panned)
  2495.     graph_edit = createPannedGraphEdit(parent, "graph_edit", args, arg);
  2496.     else
  2497.     graph_edit = createScrolledGraphEdit(parent, "graph_edit", args, arg);
  2498.  
  2499.     last_origin = graph_edit;
  2500.  
  2501.     graph_popup_w = 
  2502.     MMcreatePopupMenu(graph_edit, "graph_popup", graph_popup);
  2503.     node_popup_w = 
  2504.     MMcreatePopupMenu(graph_edit, "node_popup", node_popup);
  2505.  
  2506.     disp_graph->callHandlers();
  2507.  
  2508.     XtAppAddActions (app_context, actions, XtNumber (actions));
  2509.     XtManageChild (graph_edit);
  2510.  
  2511.     graph_cmd_w = 
  2512.     verify(XmCreateRowColumn(parent, "graph_cmd_w", NULL, 0));
  2513.  
  2514.     verify(XtVaCreateManagedWidget("graph_arg_label",
  2515.                    xmLabelWidgetClass,
  2516.                    graph_cmd_w,
  2517.                    NULL));
  2518.  
  2519.     graph_arg = new ArgField (graph_cmd_w, "graph_arg");
  2520.  
  2521.     registerOwnConverters();
  2522.  
  2523.     MMcreateWorkArea(graph_cmd_w, "graph_cmd_area", graph_cmd_area);
  2524.     MMaddCallbacks(graph_cmd_area);
  2525.     XtManageChild(graph_cmd_w);
  2526.  
  2527.     XtWidgetGeometry size;
  2528.     size.request_mode = CWHeight;
  2529.     XtQueryGeometry(graph_cmd_w, NULL, &size);
  2530.     XtVaSetValues(graph_cmd_w,
  2531.           XmNpaneMaximum, size.height,
  2532.           XmNpaneMinimum, size.height,
  2533.           NULL);
  2534.  
  2535. #ifdef LESSTIF_VERSION
  2536.     // Not available in LessTif 0.1
  2537.     edit_displays_dialog_w = 0;
  2538.     display_list_w         = 0;
  2539. #else
  2540.     // Create display editor
  2541.     edit_displays_dialog_w =
  2542.     verify(XmCreatePromptDialog(graph_edit, "edit_displays_dialog", 
  2543.                     NULL, 0));
  2544.     Delay::register_shell(edit_displays_dialog_w);
  2545.  
  2546.     XtUnmanageChild(XmSelectionBoxGetChild(edit_displays_dialog_w,
  2547.                        XmDIALOG_TEXT));
  2548.     XtUnmanageChild(XmSelectionBoxGetChild(edit_displays_dialog_w,
  2549.                        XmDIALOG_CANCEL_BUTTON));
  2550.     XtUnmanageChild(XmSelectionBoxGetChild(edit_displays_dialog_w,
  2551.                        XmDIALOG_SELECTION_LABEL));
  2552.  
  2553.     Widget form1 = 
  2554.     verify(XmCreateRowColumn(edit_displays_dialog_w, "form1", NULL, 0));
  2555.  
  2556.     Widget label =
  2557.     verify(XmCreateLabel(form1, "displays", NULL, 0));
  2558.  
  2559.     Widget form2 = 
  2560.     verify(XmCreateRowColumn(form1, "form2", NULL, 0));
  2561.  
  2562.     arg = 0;
  2563.     display_list_w = 
  2564.     verify(XmCreateScrolledList(form2, "displays", args, arg));
  2565.     Widget buttons = 
  2566.     verify(MMcreateWorkArea(form2, "buttons", display_area));
  2567.     MMaddCallbacks (display_area);
  2568.  
  2569.     XtManageChild (buttons);
  2570.     XtManageChild (display_list_w);
  2571.     XtManageChild (label);
  2572.     XtManageChild (form2);
  2573.     XtManageChild (form1);
  2574. #endif
  2575.  
  2576.     XtAddCallback(graph_edit,
  2577.           XtNselectionChangedCallback,
  2578.           UpdateDisplayEditorSelectionCB,
  2579.           0);
  2580.     XtAddCallback(graph_edit,
  2581.           XtNcompareNodesCallback,
  2582.           CompareNodesCB,
  2583.           0);
  2584.  
  2585.     if (display_list_w)
  2586.     {
  2587.     XtAddCallback(display_list_w,
  2588.               XmNsingleSelectionCallback,
  2589.               UpdateGraphEditorSelectionCB,
  2590.               0);
  2591.     XtAddCallback(display_list_w,
  2592.               XmNmultipleSelectionCallback,
  2593.               UpdateGraphEditorSelectionCB,
  2594.               0);
  2595.     XtAddCallback(display_list_w,
  2596.               XmNextendedSelectionCallback,
  2597.               UpdateGraphEditorSelectionCB,
  2598.               0);
  2599.     XtAddCallback(display_list_w,
  2600.               XmNbrowseSelectionCallback,
  2601.               UpdateGraphEditorSelectionCB,
  2602.               0);
  2603.     }
  2604.  
  2605.     if (edit_displays_dialog_w)
  2606.     {
  2607.     XtAddCallback(edit_displays_dialog_w,
  2608.               XmNokCallback,
  2609.               UnmanageThisCB,
  2610.               edit_displays_dialog_w);
  2611.     XtAddCallback(edit_displays_dialog_w,
  2612.               XmNhelpCallback,
  2613.               ImmediateHelpCB,
  2614.               0);
  2615.     }
  2616.  
  2617.     // Reset argument field and display editor buttons
  2618.     set_args();
  2619. }
  2620.